package com.android.camtube;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;



public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
	
/**************************/
/*****   Attributes   *****/
/**************************/

	private SurfaceHolder surfHolder;
	private CameraHandler camHandler;

	
	
/***********************/
/*****   Methods   *****/
/***********************/
	
	public CameraPreview(Context context, AttributeSet attribs) {
		super(context, attribs);
	}
	
	public void initCamPreview(CameraHandler camHandler) {
		this.camHandler = camHandler;
		
		// Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
		surfHolder = getHolder();
		surfHolder.addCallback(this);
		surfHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}
	

	public void surfaceCreated(SurfaceHolder holder) {
		try {
			camHandler.setPreviewDisplay(holder);
		} catch (IOException e) {
			camHandler.release();
			camHandler = null;
		}
		
	}
	
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		// Now that the size is known, set up the camera parameters and begin
        // the preview.
        CameraParameters parameters = camHandler.getParameters();
        
        camHandler.getSupportedParameters(parameters); 
        parameters.previewSize = getOptimalPreviewSize(parameters.supportedPreviewSizes, width, height);
        camHandler.setParameters(parameters);
        camHandler.startPreview();
	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		camHandler.stopPreview();
		camHandler.release();
		camHandler = null;
	}
	
	private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
        final double ASPECT_TOLERANCE = 0.05;
        double targetRatio = (double) w / h;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        int targetHeight = h;

        // Try to find an size match aspect ratio and size
        for(Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if(Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if(Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if(optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }
	
}